<?php
require_once "DatabaseManager.php";
require_once "utils/Constants.php";
require_once "UsersManager.php";
require_once "data/Booking.php";


class NotificationsManager extends DatabaseManager {
	private function registerForCourseNotification($courseCode, $deviceId) {
			// Get Language
			$headers =  apache_request_headers();
			$language = null;
			if (isset($headers['Accept-Language']))
				$language = $headers['Accept-Language'];
			// Check if $courseCode, $deviceId pair isn't already in the DB
			$queryString = "SELECT id FROM devices_courses WHERE course_code = '$courseCode' AND device_id = '$deviceId'";
			$queryResults = mysql_query($queryString, $this->connection);
			$numberOfRows = mysql_num_rows($queryResults);
			if ($numberOfRows > 0) {
				// Device already registered for this course
				$row = mysql_fetch_array($queryResults);
				$id = $row['id'];	
				
				$jsonResponse = array();
				$jsonResponse[MESSAGE] = Strings::DEVICE_ALREADY_REGISTERED;
				$jsonResponse[JSON_Tags::ID] = $id;
				
				$this->response($this->toJSON($jsonResponse), StatusCodes::STATUS_CODE_CONFLICT);	
			}
			// Device isn't registered for this course
			if ($language != null) {
				$queryString = "INSERT INTO devices_courses (course_code, device_id, language) VALUES ('$courseCode', '$deviceId', '$language')";
			} else {
				$queryString = "INSERT INTO devices_courses (course_code, device_id) VALUES ('$courseCode', '$deviceId')";
			}
			$success= mysql_query($queryString, $this->connection);
			if ($success) {
				// Successs
				$id = mysql_insert_id();
				$jsonResponse[JSON_Tags::ID] = $id;
				$this->response($this->toJSON($jsonResponse), StatusCodes::STATUS_CODE_SUCCESS);	
			} else {
				// Error
				$jsonResponse[MESSAGE] = Strings::DATA_BASE_ERROR;
				$this->response($this->toJSON($jsonResponse), StatusCodes::STATUS_CODE_SERVER_ERROR);
			}
	}
	
	private function unRegisterForCourseNotification($id, $deviceId) {
			$queryString = "DELETE FROM devices_courses WHERE id = $id AND device_id = '$deviceId'";
			mysql_query($queryString, $this->connection);
			$affectedRows = mysql_affected_rows();
			if ($affectedRows > 0) {
				$this->response(null, StatusCodes::STATUS_CODE_NO_CONTENT);	
			} else {
				// Invalid id/device pair
				$jsonResponse[MESSAGE] = Strings::INVALID_ID_DEVICE_PAIR;
				$this->response($this->toJSON($jsonResponse), StatusCodes::STATUS_CODE_BAD_REQUEST);
			}
	}
    
    public function createMessageAndNotifyDevices($format, $courseCode, $bookingStartDate) {
        // Get devices and courses
        $devices = $this->getDevicesForCourse($courseCode);
        $courseName = $this->getCourseName($courseCode);
        
        // Build the message
        $message = sprintf($format, $courseName, $bookingStartDate);
        
        // Notify devices
        $this->notifyDevicesWithMessage($devices, $message);
    }
    
    private function getDevicesForCourse($courseCode) {
        $courseCode = strtolower($courseCode);
        $queryString = "SELECT device_id FROM devices_courses WHERE LOWER(course_code) = '$courseCode'";
        $queryResults = mysql_query($queryString, $this->connection);
        $numberOfRows = mysql_num_rows($queryResults);
        $jsonResults = array();
        if ($numberOfRows > 0) {
            // Devices were found
            $devices = array();
            while ($row = mysql_fetch_array($queryResults)) {
                array_push($devices, $row['device_id']);
            }
        }
        
        return $devices;
    }
    
    private function getCourseName($courseCode) {
        $queryString = "SELECT name FROM courses WHERE LOWER(code) = '$courseCode'";
        $queryResults = mysql_query($queryString, $this->connection);
        $numberOfRows = mysql_num_rows($queryResults);
        if ($numberOfRows >0) {
            $row = mysql_fetch_array($queryResults);
            return $row['name'];
        }
        return NULL;
    }
    
    private function notifyDevicesWithMessage($devices, $message) {
        // Put your private key's passphrase here:
        $passphrase = 'Je7aeza8';
        
        ////////////////////////////////////////////////////////////////////////////////
        
        $ctx = stream_context_create();
        stream_context_set_option($ctx, 'ssl', 'local_cert', 'managers/ck.pem');
        stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
        
        // Open a connection to the APNS server
        $fp = stream_socket_client(
                                   'ssl://gateway.sandbox.push.apple.com:2195', $err,
                                   $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
        
        if (!$fp)
            exit("Failed to connect: $err $errstr" . PHP_EOL);
        
        // Create the payload body
        $body['aps'] = array(
                             'alert' => $message,
                             'sound' => 'default'
                             );
        
        // Encode the payload as JSON
        $payload = json_encode($body);
        
        foreach ($devices as $deviceToken) {
            // Build the binary notification
            $msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;
            
            // Send it to the server
            $result = fwrite($fp, $msg, strlen($msg));
            
        }
        // Close the connection to the server
        fclose($fp);
    }
	
	public function processApi() {
		// Check authorization token
		$userManager = new UsersManager();
		$userInfo = $userManager->getUserInfoForAuthorization();
		$METHOD = $this->get_request_method();
        $this->_request = file_get_contents("php://input");
		if ($METHOD == "POST") {
				$postContent = json_decode($this->_request, true);
				if ($postContent) {
					if (isset($postContent[JSON_Tags::COURSE_CODE])) {
							$courseCode = addslashes($postContent[JSON_Tags::COURSE_CODE]);	
					} else {
							// CourseCodeNotSet	
							$jsonResults[MESSAGE] = Strings::COURSE_CODE_NOT_SET;
							$this->response($this->toJSON($jsonResults), StatusCodes::STATUS_CODE_BAD_REQUEST);
					}
					if (isset($postContent[JSON_Tags::DEVICE_ID])) {
							$deviceId = addslashes($postContent[JSON_Tags::DEVICE_ID]);	
					} else {
							// DeviceId not set
							$jsonResults[MESSAGE] = Strings::DEVICE_ID_NOT_SET;
							$this->response($this->toJSON($jsonResults), StatusCodes::STATUS_CODE_BAD_REQUEST);	
					}
					if (count($postContent) != 2) {
							// If any extra elements, invalidate the JSON	
							$jsonResults[MESSAGE] = Strings::BAD_REQUEST;
							$this->response($this->toJSON($jsonResults), StatusCodes::STATUS_CODE_BAD_REQUEST);
					}
					$this->registerForCourseNotification($courseCode, $deviceId);
				} else {
						$jsonResults[MESSAGE] = Strings::BAD_REQUEST;
						$this->response($this->toJSON($jsonResults), StatusCodes::STATUS_CODE_BAD_REQUEST); 
				}
		} else if ($METHOD == 'DELETE') {
				$deleteContent = json_decode($this->_request, true);
				if ($deleteContent) {
					if (isset($deleteContent[JSON_Tags::DEVICE_ID])) {
							$deviceId = addslashes($deleteContent[JSON_Tags::DEVICE_ID]);	
					} else {
							// DeviceId not set
							$jsonResults[MESSAGE] = Strings::DEVICE_ID_NOT_SET;
							$this->response($this->toJSON($jsonResults), StatusCodes::STATUS_CODE_BAD_REQUEST);	
					}				
					if (count($deleteContent) != 1) {
							// If any extra elements, invalidate the JSON	
							$jsonResults[MESSAGE] = Strings::BAD_REQUEST;
							$this->response($this->toJSON($jsonResults), StatusCodes::STATUS_CODE_BAD_REQUEST);
					}
				} else {
						$jsonResults[MESSAGE] = Strings::BAD_REQUEST;
						$this->response($this->toJSON($jsonResults), StatusCodes::STATUS_CODE_BAD_REQUEST); 
				}
				$id = addslashes($_GET['id']);
				$this->unRegisterForCourseNotification($id, $deviceId);
		} else {
			// Not supported method	
			$jsonResults[MESSAGE] = Strings::HTTP_METHOD_NOT_SUPPORTED;
			$this->response($this->toJSON($jsonResults), StatusCodes::STATUS_CODE_BAD_REQUEST);
		}
	}
}
?>